﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RRRSRoguelike.Managers;
using RRRSRoguelike.Entities;
using System.Drawing;
using System.Threading;
using RRRSRoguelike.Helpers;

namespace RRRSRoguelike.Screens
{
    class DungeonScreen:Screen
    {

        #region variables 
            public ReplayScreen replayScreen;
            public QuitScreen QuitScreen;
            TextScreen concludeGameScreen;
            Player player;
            private bool hasJumped = false;
            private bool hasFired = false;
            bool playerMoved;
            bool processMonsters;
            bool drawPanels = true;

            public ActionManager ActionManager;
        # endregion

        #region constructors
        public DungeonScreen()
        {
            ActionManager = new ActionManager();
            //Sets up the default keys
            ActionManager.SetDefaultKeys();

            Panels = new List<Panel>();
            Panels.Add(new Panel(new Point(4, 1), DungeonVisualizer.GetScreenWidth() - 9, 5));
            Panels.Add(new Panel(new Point(4, 27), DungeonVisualizer.GetScreenWidth() - 9, 5));
            //Panels.Add (new Panel(new Point(4, 7), 20, Constants.DungeonHeight + 2));
            //Panels.Add ( new Panel(new Point(46, 7), 20, Constants.DungeonHeight + 2));

            replayScreen = new ReplayScreen();
            QuitScreen = new QuitScreen();
        }
        #endregion

        #region methods

        public void ReDraw()
        {
            drawPanels = true;
            DrawTitle();
            DoDraw();
        }

        public override void Show()
        {
            Show(-1);
            base.Show();
        }
        
        public void Show(int seed =-1)
        {
            
            Console.Clear();
            drawPanels = true;
            StartGame(seed);
            MainGameLoop();

            base.Show();
        }

        private void StartGame(int seed = -1)
        {
            DungeonManager.Instance.Initialize(seed);

            GameManager.Instance.GameTime.Restart();

            //Swapping these two lines around stopped the flicker, no idea why!
            //this draws the panels
            DungeonManager.Instance.DungeonVisualizer.ForceFullVisualization(DungeonManager.Instance.DungeonLevel);
            //this does what it says on the tin. 
            DungeonManager.Instance.ForceRedraw();

            DrawTitle();
            
            player = DungeonManager.Instance.CreatureManager.Player;

            hasJumped = false;
            hasFired = false;

            MainGameLoop();

            if (DungeonManager.Instance.PlayerHasWon.Value)
            { concludeGameScreen = new TextScreen("Victory"); }
            else
            { concludeGameScreen = new TextScreen("GameOver"); }
                
            concludeGameScreen.Show();

            replayScreen.Show();
        }

        private void DrawTitle()
        {
            Panels[0].Clear();
            //removed seed
            Panels[0].Write(DungeonManager.Instance.DungeonLevel.ToString(), ConsoleColor.White, TextAlignment.Center); 
                //+ "  Seed: " + DungeonManager.Instance.Seed.ToString());
        }

        private void MainGameLoop()
        {
            while (DungeonManager.Instance.IsGameActive)
            {
                
                //read input
                HandleInput();

                //do logic
                DoLogic();

                //Draw
                DoDraw();

            }
        }

private void DoDraw()
{
                if (drawPanels)
                {
                    foreach (Panel p in Panels)
                        p.Draw();

                    drawPanels = false;
                }
                DisplayHUD();

                DungeonManager.Instance.DrawDungeon();
}

        private void DisplayHUD()
        {
            if (DungeonManager.Instance.CreatureManager.Player.Inventory.Any<Sword>())
            {
                StringBuilder sb = new StringBuilder("Sword: ");

                for (int i = 0; i < DungeonManager.Instance.CreatureManager.Player.Inventory[0].UsesRemaining; i++)
                {
                    sb.Append("*");
                }

                Panels[1].Write(sb.ToString(), ConsoleColor.White,TextAlignment.Center);

            }
            else
            {
                Panels[1].Clear();
            }

        }

        public void DoLogic()
        {
            processMonsters = true;
            playerMoved = true;
            DungeonManager.Instance.Redraw = true;

            ProcessInput();

            //Can later be part of the prop manager perhaps or the fireball itself
            Fireball fireball = DungeonManager.Instance.PropManager.Fireball;
            if (fireball.Active)
                ProcessFireball(fireball);

            // does things like auto pick up sword and take stairs
            if (playerMoved)
                CheckNewTile();

            if (processMonsters)
            {
                DungeonManager.Instance.CreatureManager.ProcessMonsters();
            }
        }

        public void HandleInput()
        {
            GameManager.Instance.InputManager.ReadKeys();
        }

        private void CheckNewTile()
        {
            Point newPosition = new Point(player.X, player.Y);

            //auto pick up sword
            if (DungeonManager.Instance.DungeonLevel.GetTile(newPosition) is Sword && player.Inventory.Count == 0)
            {
                Sword sword = (Sword)DungeonManager.Instance.DungeonLevel.GetTile(newPosition);
                player.Inventory.Add(sword);
                DungeonManager.Instance.PropManager.RemoveSword(sword);
            }

            // auto take stairwell
            else if (DungeonManager.Instance.DungeonLevel.GetTile(newPosition) is Stairwell)
            {
                //check for victory
                if (DungeonManager.Instance.CurrentDungeonLevel >= 5)
                {
                    DungeonManager.Instance.gameOver = true;
                }
                else
                {
                    MoveToNextLevel();
                }
            }
        }

        private void MoveToNextLevel()
        {
            hasJumped = false;
            hasFired = false;

            //no sword on next level. Murha, ha, ha, ha!!!
            //player.Inventory.Clear();
            //sword now has three uses

            DungeonManager.Instance.CurrentDungeonLevel++;
            DungeonManager.Instance.Dungeon.Levels.Add(new DungeonLevel(DungeonManager.Instance.CurrentDungeonLevel, Constants.DungeonWidth, Constants.DungeonHeight));
            DungeonManager.Instance.DungeonLevel.CreateRandomDungeonObjects();
            processMonsters = false;
            GameManager.Instance.DungeonScreen.ReDraw();
        }

        private void ProcessInput()
        {
            ActionManager ActionManager = GameManager.Instance.DungeonScreen.ActionManager;
            Player player = DungeonManager.Instance.CreatureManager.Player;

            //This checks until one is true as we can only have on action press.
            if (ActionManager.IsActionPushed(Actions.North))
                playerMoved = processMonsters = player.MovePlayer(Direction.N);
            else if (ActionManager.IsActionPushed(Actions.South))
                playerMoved = processMonsters = player.MovePlayer(Direction.S);
            else if (ActionManager.IsActionPushed(Actions.East))
                playerMoved = processMonsters =player.MovePlayer(Direction.E);
            else if (ActionManager.IsActionPushed(Actions.West))
                playerMoved = processMonsters = player.MovePlayer(Direction.W);
            else if (ActionManager.IsActionPushed(Actions.JumpNorth) && !hasJumped)
            {
                playerMoved = processMonsters = player.MovePlayer(Direction.N, Constants.JumpDistance);
                hasJumped = true;
            }
            else if (ActionManager.IsActionPushed(Actions.JumpSouth) && !hasJumped)
            {
                playerMoved = processMonsters = player.MovePlayer(Direction.S, Constants.JumpDistance);
                hasJumped = true;

            }
            else if (ActionManager.IsActionPushed(Actions.JumpEast) && !hasJumped)
            {
                playerMoved = processMonsters = player.MovePlayer(Direction.E, Constants.JumpDistance);
                hasJumped = true;
            }
            else if (ActionManager.IsActionPushed(Actions.JumpWest) && !hasJumped)
            {
                playerMoved = processMonsters = player.MovePlayer(Direction.W, Constants.JumpDistance);
                hasJumped = true;
            }
            //else if (ActionManager.IsActionPushed(Actions.ShootNorth) && !hasFired)
            //{
            //    Constants.Direction d = Constants.Direction.N;
            //    ShootFireball(d);
            //}
            //else if (ActionManager.IsActionPushed(Actions.ShootSouth) && !hasFired)
            //{
            //    Constants.Direction d = Constants.Direction.S;
            //    ShootFireball(d);
            //}
            //else if (ActionManager.IsActionPushed(Actions.ShootEast) && !hasFired)
            //{
            //    Constants.Direction d = Constants.Direction.E;
            //    ShootFireball(d);
            //}
            //else if (ActionManager.IsActionPushed(Actions.ShootWest) && !hasFired)
            //{
            //    Constants.Direction d = Constants.Direction.W;
            //    ShootFireball(d);
            //}
            else if (ActionManager.IsActionPushed(Actions.Look))
            {
                DoLook();

                processMonsters = playerMoved = false;
            }
            else if (ActionManager.IsActionPushed(Actions.Wait))
            {
                playerMoved = false;
            }
            else if (ActionManager.IsActionPushed(Actions.Quit))
            {
                GameManager.Instance.DungeonScreen.QuitScreen.Show();
                
                DungeonManager.Instance.DungeonVisualizer.ForceFullVisualization(DungeonManager.Instance.DungeonLevel);

                processMonsters =playerMoved = false;
            }
            else if (ActionManager.IsActionPushed(Actions.Help))
            {
                TextScreen hs = new TextScreen("Help");
                hs.Show();
                DungeonManager.Instance.DungeonVisualizer.ForceFullVisualization(DungeonManager.Instance.DungeonLevel);
                processMonsters = playerMoved = false;
            }
            else if (ActionManager.IsActionPushed(Actions.FollowToggle))
            {
                //Toggle sound
                if (Properties.Settings.Default.FollowToggle)
                    Properties.Settings.Default.FollowToggle = false;
                else
                {
                    Properties.Settings.Default.FollowToggle = true;
                }
                Properties.Settings.Default.Save();

                processMonsters = playerMoved = false;

            }
            else if (ActionManager.IsActionPushed(Actions.SoundToggle))
            {
                //Toggle sound
                if (Properties.Settings.Default.SoundToggle)
                    Properties.Settings.Default.SoundToggle = false;
                else
                {
                    Properties.Settings.Default.SoundToggle = true;
                    GameManager.Instance.SoundManager.PlaySound(SoundList.Pluck.ToString());
                }
                Properties.Settings.Default.Save();

                processMonsters = playerMoved =false;
                
            }
            else if (ActionManager.IsActionPushed(Actions.ChangeAnimationSpeed))
            {
                Properties.Settings.Default.AnimationSpeed -= 33;
                if (Properties.Settings.Default.AnimationSpeed < 34)
                    Properties.Settings.Default.AnimationSpeed = 100;

                Properties.Settings.Default.Save();

                GameManager.Instance.SoundManager.PlaySound(SoundList.Pluck.ToString());

                processMonsters = playerMoved =false;
            }
            else
            {
                processMonsters = playerMoved = DungeonManager.Instance.Redraw = false;
            }
        }

        private void DoLook()
        {
            bool newTile = false;
            bool look = true;
            Tile lookTile = DungeonManager.Instance.PropManager.LookTile;
            lookTile.Active = true; 
            lookTile.Position = player.Position;

            while(look)
            {
                HandleInput();

                if (ActionManager.IsActionPushed(Actions.North))
                {lookTile.Y -= 1;newTile = true;}
                else if (ActionManager.IsActionPushed(Actions.South))
                {lookTile.Y += 1;newTile = true;}
                else if (ActionManager.IsActionPushed(Actions.East))
                {lookTile.X += 1;newTile = true;}
                else if (ActionManager.IsActionPushed(Actions.West))
                {lookTile.X -= 1;newTile = true;}
                else if (ActionManager.IsActionPushed(Actions.Quit) || ActionManager.IsActionPushed(Actions.Look))
                    look = false;

                if (newTile)
                {
                    //limit

                    lookTile.Position = DungeonLevel.ClampToDungeon(lookTile.Position);

                    Tile viewTile = (Tile)DungeonManager.Instance.DungeonLevel.GetTile(lookTile.Position);
                    lookTile.ImageCharacter = viewTile.ImageCharacter;
                    lookTile.Color = ConsoleColor.Cyan;

                    string description = "A mystery object.";

                    if (viewTile.Description != null)
                        description = viewTile.Description;

                    Panels[1].Write(description, ConsoleColor.White, TextAlignment.Center);

                    DungeonManager.Instance.ForceRedraw();
                    newTile = false;
                }
            //Draw
            }
            lookTile.Active = false;
            DungeonManager.Instance.ForceRedraw();
        }

        private void ShootFireball(Direction d)
        {
            DungeonManager.Instance.PropManager.Fireball = new Fireball(player.Position, d);
            DungeonManager.Instance.PropManager.Fireball.Active = true;
            hasFired = true;
        }
        
        private static void ProcessFireball(Fireball fireball)
        {
            while (DungeonManager.Instance.DungeonLevel.IsOKToMove(fireball.Position))
            {
                //Do fireball stuff
                //DungeonManager.Instance.PropManager.Fireball
                //Fireball move
                DungeonManager.Instance.PropManager.Fireball.Move(fireball.Position, fireball.Direction, 1);
                //Fireball kill monsters
                List<Monster> monstersInBattle = DungeonManager.Instance.CreatureManager.monsters.Where(m => m.X == fireball.X && m.Y == fireball.Y).ToList();
                foreach (Monster m in monstersInBattle)
                {
                    fireball.Kill(m);

                    DungeonManager.Instance.PlaySound(SoundList.Battle);

                    fireball.ImageCharacter = "*";

                    DungeonManager.Instance.DungeonVisualizer.Flash(fireball);

                    fireball.ImageCharacter = "o";
                    fireball.Color = ConsoleColor.Magenta;
                }
                //Draw
                DungeonManager.Instance.ForceRedraw();

            }
            DungeonManager.Instance.PropManager.Fireball.Active = false;
            DungeonManager.Instance.Redraw = true;
        }
        #endregion

    }
}
